"""
Pytest配置文件
设置测试环境和共享fixture
"""

import pytest
import os
import sys
import yaml
from typing import Dict, Any

# 添加项目根目录到Python路径
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from utils.driver_manager import DriverManager
from utils.config_manager import config_manager


def pytest_configure(config):
    """Pytest配置"""
    # 创建必要的目录
    os.makedirs("reports", exist_ok=True)
    os.makedirs("reports/screenshots", exist_ok=True)
    os.makedirs("reports/logs", exist_ok=True)
    
    # 设置测试标记
    config.addinivalue_line("markers", "slow: 标记为慢速测试")
    config.addinivalue_line("markers", "ui: 标记为UI测试")
    config.addinivalue_line("markers", "functional: 标记为功能测试")
    config.addinivalue_line("markers", "smoke: 标记为冒烟测试")
    config.addinivalue_line("markers", "regression: 标记为回归测试")


@pytest.fixture(scope="session")
def test_config():
    """获取测试配置"""
    return config_manager.get_test_config()


@pytest.fixture(scope="session")
def device_config():
    """获取设备配置"""
    platform = os.getenv("TEST_PLATFORM", "android")
    return config_manager.get_device_config(platform)


@pytest.fixture(scope="session")
def test_data():
    """加载测试数据"""
    test_data_path = "test_data/login_test_data.yaml"
    if os.path.exists(test_data_path):
        with open(test_data_path, 'r', encoding='utf-8') as file:
            return yaml.safe_load(file)
    return {}


@pytest.fixture(scope="function")
def driver_manager():
    """创建驱动管理器fixture"""
    platform = os.getenv("TEST_PLATFORM", "android")
    driver_mgr = DriverManager(platform=platform)
    
    try:
        driver_mgr.start_driver()
        yield driver_mgr
    finally:
        driver_mgr.quit_driver()


@pytest.fixture(scope="function")
def driver_manager_ios():
    """创建iOS驱动管理器fixture"""
    driver_mgr = DriverManager(platform="ios")
    
    try:
        driver_mgr.start_driver()
        yield driver_mgr
    finally:
        driver_mgr.quit_driver()


@pytest.fixture(scope="function")
def driver_manager_android():
    """创建Android驱动管理器fixture"""
    driver_mgr = DriverManager(platform="android")
    
    try:
        driver_mgr.start_driver()
        yield driver_mgr
    finally:
        driver_mgr.quit_driver()


def pytest_runtest_setup(item):
    """测试运行前设置"""
    # 检查是否需要特定平台
    if hasattr(item, 'get_closest_marker'):
        if item.get_closest_marker('ios_only'):
            if os.getenv("TEST_PLATFORM") != "ios":
                pytest.skip("此测试需要iOS平台")
        elif item.get_closest_marker('android_only'):
            if os.getenv("TEST_PLATFORM") != "android":
                pytest.skip("此测试需要Android平台")


def pytest_runtest_teardown(item, nextitem):
    """测试运行后清理"""
    # 这里可以添加测试后的清理逻辑
    pass


def pytest_collection_modifyitems(config, items):
    """修改测试收集"""
    # 根据标记重新排序测试
    for item in items:
        if item.get_closest_marker('smoke'):
            item.add_marker(pytest.mark.order(1))
        elif item.get_closest_marker('functional'):
            item.add_marker(pytest.mark.order(2))
        elif item.get_closest_marker('ui'):
            item.add_marker(pytest.mark.order(3))
        elif item.get_closest_marker('regression'):
            item.add_marker(pytest.mark.order(4))


def pytest_html_report_title(report):
    """设置HTML报告标题"""
    report.title = "APP自动化测试报告"


def pytest_html_results_table_header(cells):
    """自定义HTML报告表头"""
    cells.insert(2, html.th('Description'))
    cells.pop()


def pytest_html_results_table_row(report, cells):
    """自定义HTML报告行"""
    cells.insert(2, html.td(report.description))
    cells.pop()


@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """生成测试报告"""
    outcome = yield
    report = outcome.get_result()
    
    # 设置测试描述
    report.description = str(item.function.__doc__)
    
    # 如果测试失败，截图
    if report.when == "call" and report.failed:
        try:
            # 获取driver_manager fixture
            driver_mgr = item.funcargs.get('driver_manager')
            if driver_mgr and driver_mgr.driver:
                screenshot_path = driver_mgr.take_screenshot(f"failure_{item.name}.png")
                if screenshot_path:
                    # 将截图添加到HTML报告
                    with open(screenshot_path, "rb") as f:
                        screenshot_data = f.read()
                    report.extra.append(pytest_html.extras.image(screenshot_data))
        except Exception as e:
            print(f"截图失败: {e}")


# 自定义命令行选项
def pytest_addoption(parser):
    """添加自定义命令行选项"""
    parser.addoption(
        "--platform",
        action="store",
        default="android",
        help="测试平台: android 或 ios"
    )
    parser.addoption(
        "--device",
        action="store",
        help="设备名称或ID"
    )
    parser.addoption(
        "--app-path",
        action="store",
        help="应用APK/IPA文件路径"
    )
    parser.addoption(
        "--parallel",
        action="store_true",
        help="并行执行测试"
    )
    parser.addoption(
        "--headless",
        action="store_true",
        help="无头模式运行"
    )


@pytest.fixture(scope="session")
def cmdopt(request):
    """获取命令行选项"""
    return {
        "platform": request.config.getoption("--platform"),
        "device": request.config.getoption("--device"),
        "app_path": request.config.getoption("--app-path"),
        "parallel": request.config.getoption("--parallel"),
        "headless": request.config.getoption("--headless")
    } 